#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <stdint.h>
#include <sys/time.h>
#include <stdio.h>

#include "lite_frame_protocol.h"

/**
 * @brief Invert uint8.
 *
 * This function inverts the bits of a uint8_t value.
 *
 * @param dst_buf Pointer to the destination buffer.
 * @param src_buf Pointer to the source buffer.
 */
static void invert_uint8(uint8_t  *dst_buf, uint8_t  *src_buf)
{
    uint32_t i;
    uint8_t  tmp[4] = {0};

    for (i = 0; i < 8; i++) {
        if (src_buf[0] & (1 << i))
        tmp[0] |= 1 << (7-i);
    }
    dst_buf[0] = tmp[0];
}

/**
 * @brief Invert uint16.
 *
 * This function inverts the bits of a uint16_t value.
 *
 * @param dst_buf Pointer to the destination buffer.
 * @param src_buf Pointer to the source buffer.
 */
static void invert_uint16(uint16_t *dst_buf, uint16_t *src_buf)
{
    uint32_t i;
    uint16_t tmp = 0;

    for (i = 0; i < 16; i++) {
        if (src_buf[0] & (1 << i))
        tmp |= 1 << (15 - i);
    }
    dst_buf[0] = tmp;
}

/**
 * @brief Calculate CRC16 CCITT.
 *
 * This function calculates the CRC16 CCITT checksum of a given data buffer.
 *
 * @param data Pointer to the data buffer.
 * @param data_len Length of the data buffer in bytes.
 * @return int32_t CRC16 CCITT checksum.
 */
static int32_t crc16_ccitt(uint8_t *data, uint32_t data_len) {
    uint16_t crc_in = 0xFFFF;
    uint16_t crc_poly = 0x1021;
    uint8_t data_byte = 0;
    uint32_t i = 0;

    while (data_len--) {
        data_byte = *(data++);
        invert_uint8(&data_byte, &data_byte);
        crc_in ^= (data_byte << 8);

        for (i = 0; i < 8; i++) {
            if (crc_in & 0x8000)
                crc_in = (crc_in << 1) ^ crc_poly;
            else
                crc_in = crc_in << 1;
        }
    }

    invert_uint16(&crc_in, &crc_in);
    return crc_in;
}

/**
 * @brief Debug ring buffer data.
 *
 * This function debugs the data in a ring buffer.
 *
 * @param p_spi_info_str Pointer to the SPI information string.
 * @param buf Pointer to the data buffer.
 * @param len Length of the data buffer in bytes.
 * @return int32_t Status code.
 */
static int32_t ring_buf_data_debug(char *p_spi_info_str, const uint8_t *buf, int32_t len)
{
    int32_t i = 0, j = 0;
    int32_t m = 16;
    int32_t mul_info_cnt = len / m;
    int32_t remain = len % m;

    if (NULL != p_spi_info_str) {
        clog_log_debug("%s\nring_buf: data_len:%d mul_info_cnt:%d remain:%d\n",
            (const char *)p_spi_info_str, len, mul_info_cnt, remain);
    }

    for (i = 0; i < mul_info_cnt; i++) {
        clog_log_debug("ring_buf: 0x%04x:"
            "%02X %02X %02X %02X %02X %02X %02X %02X "
            "%02X %02X %02X %02X %02X %02X %02X %02X\n", (i*m),
            buf[(i*m) + 0], buf[(i*m) + 1], buf[(i*m) + 2], buf[(i*m) + 3],
            buf[(i*m) + 4], buf[(i*m) + 5], buf[(i*m) + 6], buf[(i*m) + 7],
            buf[(i*m) + 8], buf[(i*m) + 9], buf[(i*m) + 10], buf[(i*m) + 11],
            buf[(i*m) + 12], buf[(i*m) + 13], buf[(i*m) + 14], buf[(i*m) + 15]);
    }

    for (j = 0; j < remain; j++) {
        clog_log_debug("ring_buf: %02X \n", buf[(mul_info_cnt*m) + j]);
    }
    clog_log_debug("\n");
    return RET_OK;
}

/**
 * @brief Check if the frame is a start frame.
 *
 * This function checks whether the given frame is a start frame by inspecting
 * the frame mask at the specified offset.
 *
 * @param src_buf Pointer to the source buffer containing the frame.
 * @return int32_t link_sync_start_frame if it's a start frame,
 *                 link_sync_middle_frame if it's a middle frame,
 *                 negative error code on failure.
 */
static int32_t check_the_frame_is_start_frame(const uint8_t *src_buf)
{
    int32_t ret = RET_OK;
    uint8_t frame_mask = 0;
    
    frame_mask = src_buf[RING_BUF_FRAME_MASK_OFFSET];
    if(frame_mask & 0x01) {
        ret = link_sync_start_frame;
    } else {
        ret = link_sync_middle_frame;
    }

    return ret;
}


static int32_t data_transport_layer_set(const uint8_t *src_buf, const int32_t data_length, lite_frame_swap_t *swap)
{
    int32_t ret = RET_OK;
    frame_header_byte_t header_byte;
    int32_t tmp_data_length = 0;
    uint32_t copy_length = 0;
    uint8_t tmp_buf2;
    uint32_t tmp_buf3;

    (void)memset(&header_byte, 0, sizeof(header_byte));
    if((NULL == src_buf) || (tmp_data_length <= 0) || (tmp_data_length > RING_BUF_SWAP_SIZE)) {
        clog_log_error("input param error!\n");
        return -RET_ERR;
    }

    /* first frag set frag_cnt_total & frag_last_copy */
    if(swap->frag_cnt_total == 0) {
        if(tmp_data_length < TP_FRAGMENT_VALID_SIZE) {
            swap->frag_cnt_total = 1;
            swap->frag_last_copy = tmp_data_length;
        } else {
            tmp_data_length -= TP_FRAGMENT_VALID_SIZE;
            swap->frag_cnt_total += 1;
            swap->frag_cnt_total +=
                    tmp_data_length / (TP_FRAGMENT_VALID_SIZE);
            swap->frag_last_copy =
                    tmp_data_length % (TP_FRAGMENT_VALID_SIZE);
            if (0 != swap->frag_last_copy) {
                ++swap->frag_cnt_total;
            }
        }
    }

    tmp_buf2 = (uint8_t)tmp_data_length & (uint8_t)0xff;
    tmp_buf3 = ((uint32_t)tmp_data_length>>8) & (uint8_t)0xff;

    /* only need one frag */
    if(swap->frag_cnt_total == 1) {
        swap->frag_finish_flag = 1;
        copy_length = (uint32_t)tmp_data_length;
        header_byte.element_value.start_bit = (uint8_t)1;
        header_byte.element_value.consec_bit = (uint8_t)0;
        header_byte.element_value.end_bit = (uint8_t)1;
        swap->buf[RING_BUF_FRAME_MASK_OFFSET] = (int8_t)(header_byte.byte_value);
        swap->buf[RING_BUF_FRAME_INDEX_OFFSET] = (int8_t)(swap->frag_cnt_set);
        swap->buf[RING_BUF_TOTAL_LENGTH_OFFSET] = (int8_t)tmp_buf2;
        swap->buf[RING_BUF_TOTAL_LENGTH_OFFSET + 1] = (int8_t)tmp_buf3;

        (void)memcpy(swap->buf + RING_BUF_HEADER_SIZE, src_buf, copy_length);
        swap->frag_cnt_total = 0;
        swap->frag_last_copy = 0;
        ++swap->frag_cnt_set;
        ret = TP_FRAG_FINISH_FLAG; // tp frag finish
        goto exit;
    }

    /* need more than one frag */
    if(swap->frag_cnt_set == 0) {
        /* first frag */
        copy_length = TP_FRAGMENT_VALID_SIZE;
        header_byte.element_value.start_bit = (uint8_t)1;
        header_byte.element_value.consec_bit = (uint8_t)0;
        header_byte.element_value.end_bit = (uint8_t)0;
        swap->buf[RING_BUF_FRAME_MASK_OFFSET] = (int8_t)(header_byte.byte_value);
        swap->buf[RING_BUF_FRAME_INDEX_OFFSET] = (int8_t)(swap->frag_cnt_set);
        swap->buf[RING_BUF_TOTAL_LENGTH_OFFSET] = (int8_t)tmp_buf2;
        swap->buf[RING_BUF_TOTAL_LENGTH_OFFSET + 1] = (int8_t)tmp_buf3;
        (void)memcpy(swap->buf + RING_BUF_HEADER_SIZE, (src_buf + swap->frag_index), copy_length);

        ++swap->frag_cnt_set;
        swap->frag_index += (int32_t )copy_length;

        ret = TP_FRAG_NOT_FINISH_FLAG;
        goto exit;
    } else if (swap->frag_cnt_set
                == (swap->frag_cnt_total - 1)) {
        /* last frag */
        copy_length = (uint32_t)(swap->frag_last_copy);
        header_byte.element_value.start_bit = (uint8_t)0;
        header_byte.element_value.consec_bit = (uint8_t)1;
        header_byte.element_value.end_bit = (uint8_t)1;
        swap->buf[RING_BUF_FRAME_MASK_OFFSET] = (int8_t)(header_byte.byte_value);
        swap->buf[RING_BUF_FRAME_INDEX_OFFSET] = (int8_t)(swap->frag_cnt_set);
        swap->buf[RING_BUF_TOTAL_LENGTH_OFFSET] = (int8_t)tmp_buf2;
        swap->buf[RING_BUF_TOTAL_LENGTH_OFFSET + 1] = (int8_t)tmp_buf3;

        (void)memcpy(swap->buf + RING_BUF_HEADER_SIZE, (src_buf + swap->frag_index), copy_length);
        swap->frag_index = 0;
        swap->frag_cnt_total = 0;
        swap->frag_last_copy = 0;
        swap->frag_cnt_set = 0;
        swap->frag_finish_flag = 1;
        ret = TP_FRAG_FINISH_FLAG; // frag finish
        goto exit;
    } else {
        /* middle frag */
        copy_length = TP_FRAGMENT_VALID_SIZE;
        header_byte.element_value.start_bit = (uint8_t)0;
        header_byte.element_value.consec_bit = (uint8_t)1;
        header_byte.element_value.end_bit = (uint8_t)0;
        swap->buf[RING_BUF_FRAME_MASK_OFFSET] = (int8_t)(header_byte.byte_value);
        swap->buf[RING_BUF_FRAME_INDEX_OFFSET] = (int8_t)(swap->frag_cnt_set);
        swap->buf[RING_BUF_TOTAL_LENGTH_OFFSET] = (int8_t)tmp_buf2;
        swap->buf[RING_BUF_TOTAL_LENGTH_OFFSET + 1] = (int8_t)tmp_buf3;
        ++swap->frag_cnt_set;
        (void)memcpy(swap->buf + RING_BUF_HEADER_SIZE, src_buf+swap->frag_index, copy_length);
        swap->frag_index += (int32_t)copy_length;
        ret = TP_FRAG_NOT_FINISH_FLAG;
    }
exit:
    return ret;
}

/**
 * @brief Check if the frame is a start or end frame.
 *
 * This function checks whether the given frame is a start or end frame by
 * inspecting the frame mask at the specified offset.
 *
 * @param buf Pointer to the buffer containing the frame.
 * @return int32_t start_frame if it's a start frame,
 *                 end_frame if it's an end frame,
 *                 single_frame if it's a single frame,
 *                 middle_frame if it's a middle frame,
 *                 negative error code on failure.
 */
static int32_t frame_is_start_or_end(const uint8_t *buf)
{
    int8_t ret = (int8_t)-1;
    frame_header_byte_t header_byte;
    header_byte.byte_value = buf[RING_BUF_FRAME_MASK_OFFSET];

    if ((header_byte.element_value.start_bit == (uint8_t)1)
        && (header_byte.element_value.end_bit == (uint8_t)0)
        && (header_byte.element_value.consec_bit == (uint8_t)0)) {
        ret = (int8_t)start_frame;
    } else if ((header_byte.element_value.start_bit == (uint8_t)0)
        && (header_byte.element_value.end_bit == (uint8_t)1)
        && (header_byte.element_value.consec_bit == (uint8_t)1)) {
        ret = (int8_t)end_frame;
    } else if ((header_byte.element_value.start_bit == (uint8_t)1)
        && (header_byte.element_value.end_bit == (uint8_t)1) &&
        (header_byte.element_value.consec_bit == (uint8_t)0)) {
        ret = (int8_t)single_frame;
    } else if ((header_byte.element_value.start_bit == (uint8_t)0)
        && (header_byte.element_value.end_bit == (uint8_t)0)
        && (header_byte.element_value.consec_bit == (uint8_t)1)) {
        ret = (int8_t)middle_frame;
    }

    if (ret == (int8_t)-1) {
        clog_log_error("mask byte error 0x%x\n",
            header_byte.byte_value);
    }

    return (int32_t)ret;
}

/**
 * @brief Check data link layer sync num.
 *
 * This function checks the data link layer sync num by comparing the sync num
 * value in the buffer with the expected sync num value.
 *
 * @param buf Pointer to the buffer containing the data.
 * @return int32_t link_sync_start_frame if it's a start frame,
 *                 link_sync_middle_frame if it's a middle frame,
 *                 link_sync_unknown_error if it's an unknown frame,
 *                 negative error code on failure.
 */
static int32_t data_link_layer_sync_num_check(const uint8_t *buf)
{
    int32_t ret = RET_OK;
    if (buf[RING_BUF_SYNC_CODE_OFFSET] == RING_BUF_START_FRAME_SYNC) {
        ret = link_sync_start_frame;
    } else if (buf[RING_BUF_SYNC_CODE_OFFSET] == RING_BUF_MIDDLE_FRAME_SYNC) {
        ret = link_sync_middle_frame;
    } else {
        ret = link_sync_unknown_error;
        clog_log_error("link sync:0x%x unknown error\n", buf[RING_BUF_SYNC_CODE_OFFSET]);
    }
    return ret;
}

/**
 * @brief Set data link layer sync num.
 *
 * This function sets the data link layer sync num by copying the data
 * from the source buffer to the destination buffer, while applying the
 * necessary header byte modifications.
 *
 * @param src_buf Pointer to the source buffer containing the data.
 * @param dst_buf Pointer to the destination buffer where the data will be copied.
 * @param data_length Length of the data to be copied.
 * @return int32_t RET_OK on success, negative error code on failure.
 */
static int32_t data_link_layer_sync_num_set(uint8_t *src_buf)
{
    int32_t ret = RET_OK;
    uint8_t sync_code = 0;

    ret = check_the_frame_is_start_frame(src_buf);
    if(ret == link_sync_start_frame) {
        /* first frag set sync code: 0xAA */
        sync_code = (uint8_t)RING_BUF_START_FRAME_SYNC;
    } else {
        /* middle frag set sync code: 0x55 */
        sync_code = (uint8_t)RING_BUF_MIDDLE_FRAME_SYNC;
    }

    src_buf[RING_BUF_SYNC_CODE_OFFSET] = sync_code;
    if (src_buf[RING_BUF_SYNC_CODE_OFFSET] != sync_code) {
        clog_log_error("sync_num set error!\n");
        return ret;
    }
    return ret;
}

/**
 * @brief Check data link layer rolling count.
 *
 * This function checks the data link layer rolling count by comparing the
 * rolling count value in the buffer with the expected rolling count value.
 *
 * @param buf Pointer to the buffer containing the data.
 * @return int32_t RET_OK on success, negative error code on failure.
 */
static int32_t data_link_layer_rolling_count_check(const uint8_t *buf, lite_frame_swap_t *swap)
{
    int32_t ret = RET_OK;
    if (buf[RING_BUF_ROLLING_COUNTER_OFFSET] != (swap->rc)) {
        clog_log_error("Rec rolling data error!:[0x%x] != [0x%x]\n", swap->rc,
                        buf[RING_BUF_ROLLING_COUNTER_OFFSET]);
        swap->rc = (buf[RING_BUF_ROLLING_COUNTER_OFFSET]);
        ret  = link_rolling_count_error;
    } else {
        ret  = link_rolling_count_currect;
    }
    ++swap->rc;
    return ret;
}

/**
 * @brief Set data link layer rolling count.
 *
 * This function sets the data link layer rolling count by copying the data
 * from the source buffer to the destination buffer, while applying the
 * necessary header byte modifications.
 *
 * @param buf Pointer to the buffer containing the data.
 * @return int32_t RET_OK on success, negative error code on failure.
 */
static int32_t data_link_layer_rolling_count_set(uint8_t *buf, lite_frame_swap_t *swap)
{
    int32_t ret = RET_OK;
    buf[RING_BUF_ROLLING_COUNTER_OFFSET] = swap->rc;
    if (buf[RING_BUF_ROLLING_COUNTER_OFFSET] != swap->rc) {
        ret = -RET_ERR;
        clog_log_error("rolling count set error! rc: 0x%x\n", swap->rc);
    } else {
        ret = RET_OK;
    }
    ++swap->rc;
    return ret;
}

/**
 * @brief Check data link layer crc16.
 *
 * This function checks the data link layer crc16 by comparing the crc16 value
 * in the buffer with the expected crc16 value.
 *
 * @param buf Pointer to the buffer containing the data.
 * @return int32_t RET_OK on success, negative error code on failure.
 */
static int32_t ring_buf_data_link_layer_crc16_check(uint8_t *buf)
{
    int32_t ret = RET_OK;
    uint16_t crc16_recv = *(uint16_t *)(buf + RING_BUF_CRC_OFFSET);
    uint16_t crc16_recv_temp = 0;

    buf[RING_BUF_CRC_OFFSET] = 0;
    buf[RING_BUF_CRC_OFFSET + 1] = 0;
    crc16_recv_temp = (uint16_t)crc16_ccitt(buf, RING_BUF_FRAGMENT_SIZE);
    buf[RING_BUF_CRC_OFFSET] = crc16_recv;
    buf[RING_BUF_CRC_OFFSET + 1] = crc16_recv >> 8;

    if (crc16_recv != crc16_recv_temp) {
        clog_log_error("crc check error! read: 0x%x, calc: 0x%x\n", crc16_recv, crc16_recv_temp);
        ret = link_crc16_error;
    } else {
        ret = link_crc16_currect;
    }
    return ret;
}

/**
 * @brief Set data link layer crc16.
 *
 * This function sets the data link layer crc16 by copying the data
 * from the source buffer to the destination buffer, while applying the
 * necessary header byte modifications.
 *
 * @param buf Pointer to the buffer containing the data.
 * @return int32_t RET_OK on success, negative error code on failure.
 */
static int32_t ring_buf_data_link_layer_crc16_set(uint8_t *buf)
{
    int32_t ret = RET_OK;
    uint16_t crc16_set = 0;

    buf[RING_BUF_CRC_OFFSET] = 0;
    buf[RING_BUF_CRC_OFFSET + 1] = 0;
    crc16_set = (uint16_t)crc16_ccitt((uint8_t *)buf, RING_BUF_FRAGMENT_SIZE);
    buf[RING_BUF_CRC_OFFSET] = crc16_set;
    buf[RING_BUF_CRC_OFFSET + 1] = crc16_set >> 8;
    if (*(uint16_t *)(buf + RING_BUF_CRC_OFFSET) != crc16_set) {
        clog_log_error("crc check error!");
        ret = -RET_ERR;
    }

    return ret;
}

/**
 * @brief Set data link layer.
 *
 * This function sets the data link layer by copying the data
 * from the source buffer to the destination buffer, while applying the
 * necessary header byte modifications.
 *
 * @param dst_buf Pointer to the buffer containing the data.
 * @return int32_t RET_OK on success, negative error code on failure.
 */
static int32_t ring_buf_data_link_layer_set(uint8_t *dst_buf, lite_frame_swap_t *swap)
{
    int32_t ret = RET_OK;
    ret = data_link_layer_sync_num_set(dst_buf);
    if(ret < 0) {
        clog_log_error("set data sync num error\n");
        ret = -RET_ERR;
    }
    ret = data_link_layer_rolling_count_set(dst_buf, swap);
    if(ret < 0) {
        clog_log_error("set data rolling count num error\n");
        ret = -RET_ERR;
    }
    ret = ring_buf_data_link_layer_crc16_set(dst_buf);
    if(ret < 0) {
        clog_log_error("set data crc16 num error\n");
        ret = -RET_ERR;
    }

    return ret;
}

/**
 * @brief Check data link layer.
 *
 * This function checks the data link layer by comparing the data
 * in the buffer with the expected data.
 *
 * @param buf Pointer to the buffer containing the data.
 * @return int32_t RET_OK on success, negative error code on failure.
 */
static int32_t data_link_layer_check(uint8_t *buf, lite_frame_swap_t *swap)
{
    int32_t ret = RET_OK;
    ret = data_link_layer_sync_num_check(buf);
    if(ret == link_sync_start_frame || ret == link_sync_middle_frame) {
        if(data_link_layer_rolling_count_check(buf, swap) == link_rolling_count_error) {
            clog_log_error("data_link_layer_rolling_count_check failed, ret: %d\n", ret);
            ret = link_rolling_count_error;
        }

        if(ring_buf_data_link_layer_crc16_check(buf) == link_crc16_error) {
            clog_log_error("ring_buf_data_link_layer_crc16_check failed, ret: %d\n", ret);
            ret = link_crc16_error;
        }
    } else {
        clog_log_error("data_link_layer_sync_num_check failed, ret: %d\n", ret);
        ret = link_sync_unknown_error;
    }

    return ret;
}

/**
 * @brief Set transport and data link layer.
 *
 * This function sets the transport and data link layer by copying the data
 * from the source buffer to the destination buffer, while applying the
 * necessary header byte modifications.
 *
 * @param data Pointer to the buffer containing the data.
 * @param size Size of the data in bytes.
 * @param frag_count Pointer to the variable that will store the number of fragments.
 * @return int32_t RET_OK on success, negative error code on failure.
 */
static int32_t transport_and_data_link_layer_set(const uint8_t *usr_data, const size_t data_size, lite_frame_swap_t *swap)
{
    int32_t ret = RET_OK;
    int32_t frag_count = 0;
    int32_t data_length = (int32_t)data_size;
    int32_t tp_frag_finish_flag = TP_FRAG_NOT_FINISH_FLAG;

    if((NULL == usr_data) || (NULL == swap) || (NULL == swap->buf)) {
        clog_log_error("data is null\n");
        return -RET_ERR;
    }

    /* init flag */
    swap->frag_cnt_set = 0;
    swap->frag_cnt_total = 0;
    swap->frag_last_copy = 0;
    swap->frag_index = 0;
    swap->frag_finish_flag = 0;

    while (tp_frag_finish_flag != TP_FRAG_FINISH_FLAG) {
        /* transport layer set */
        tp_frag_finish_flag = data_transport_layer_set(usr_data, data_length, swap);
        if(tp_frag_finish_flag == RET_ERR) {
            clog_log_error("transport layer set error\n");
            return -RET_ERR;
        }

        /* data link layer set */
        ret = ring_buf_data_link_layer_set(swap->buf, swap);
        if (ret == -RET_ERR) {
            clog_log_error("data link layer set error\n");
            return -RET_ERR;
        }
        usr_data += RING_BUF_FRAGMENT_SIZE;
        frag_count = frag_count + 1;
    }
    
    ret = frag_count;

    return ret;
}

/**
 * @brief Transport resolve first frame.
 *
 * This function resolves the first frame in the transport layer by
 * analyzing the frame header and setting the necessary read swap parameters.
 *
 * @param buf Pointer to the buffer containing the data.
 * @return int32_t RET_OK on success, negative error code on failure.
 */
static int32_t transport_resolve_first_frame(const uint8_t *buf, lite_frame_swap_t *swap)
{
    int32_t ret = RET_OK;
    uint8_t tmp_buf2, tmp_buf3;
    int32_t tmp_total_length = 0;

    /* Verify the first frame is a start frame */
    ret = data_link_layer_sync_num_check(buf);
    if(ret != link_sync_start_frame) {
        clog_log_error("first frame error, ret: %d\n", ret);
        ret = -RET_ERR;
        goto err;
    }

    /* Don't need check rolling count */
    /* Check crc16 of the first frame */
    if(ring_buf_data_link_layer_crc16_check(buf) == link_crc16_error) {
        clog_log_error("ring_buf_data_link_layer_crc16_check failed, ret: %d\n", ret);
        ret = -RET_ERR;
        goto err;
    }

    ret = frame_is_start_or_end(buf);
    if(ret == (int32_t)start_frame) {
        swap->frag_index = 0;
        swap->frag_finish_flag = 0;

        tmp_buf2 = buf[RING_BUF_TOTAL_LENGTH_OFFSET];
        tmp_buf3 = buf[RING_BUF_TOTAL_LENGTH_OFFSET + 1];
        tmp_total_length = (uint32_t)tmp_buf3 << 8 | tmp_buf2;

        swap->frag_cnt_total = (tmp_total_length / TP_FRAGMENT_VALID_SIZE);
        swap->frag_last_copy = tmp_total_length % TP_FRAGMENT_VALID_SIZE;
        if(swap->frag_last_copy > 0) {
            swap->frag_cnt_total++;
        }
    } else if(ret == (int32_t)single_frame) {
        swap->frag_index = 0;
        swap->frag_finish_flag = 1;
        tmp_buf2 = buf[RING_BUF_TOTAL_LENGTH_OFFSET];
        tmp_buf3 = buf[RING_BUF_TOTAL_LENGTH_OFFSET + 1];
        tmp_total_length = (uint32_t)tmp_buf3 << 8 | tmp_buf2;

        swap->frag_cnt_total = 1;
        swap->frag_last_copy = tmp_total_length;
    } else {
        clog_log_error("frame_is_start_or_end failed, ret: %d\n", ret);
        ret = -RET_ERR;
    }

    return ret;

err:
    return ret;
}

/**
 * @brief Transport resolve fragment.
 *
 * This function resolves the fragment in the transport layer by
 * analyzing the frame header and setting the necessary read swap parameters.
 *
 * @param buf Pointer to the buffer containing the data.
 * @return int32_t RET_OK on success, negative error code on failure.
 */
static int32_t transport_resolve_fragment(const uint8_t *buf, lite_frame_swap_t *swap)
{
    int32_t ret = RET_OK;

    ret = frame_is_start_or_end(buf);
    if(ret == (int32_t)start_frame) {
        swap->frag_index = 0;
        swap->frag_finish_flag = 0;
        ret = TP_FRAG_NOT_FINISH_FLAG; //read not finish
    } else if(ret == (int32_t)end_frame) {
        swap->frag_index++;
        swap->frag_finish_flag = 1;
        ret = TP_FRAG_FINISH_FLAG; //read finish
    } else if(ret == (int32_t)single_frame) {
        swap->frag_index = 0;
        swap->frag_finish_flag = 1;
        ret = TP_FRAG_FINISH_FLAG; //read finish
    } else if(ret == (int32_t)middle_frame) {
        swap->frag_index++;
        swap->frag_finish_flag = 0;
        ret = TP_FRAG_NOT_FINISH_FLAG; //read not finish
    } else {
        clog_log_error("frame_is_start_or_end failed, ret: %d\n", ret);
        ret = -RET_ERR;
    }

    return ret;
}

int32_t data_link_layer_check_interface(const uint8_t *buf, lite_frame_swap_t *swap)
{
    return data_link_layer_check(buf, swap);
}
int32_t transport_resolve_first_frame_interface(const uint8_t *buf, lite_frame_swap_t *swap)
{
    return transport_resolve_first_frame(buf, swap);
}

int32_t transport_and_data_link_layer_set_interface(const uint8_t *usr_data, const size_t data_size, lite_frame_swap_t *swap)
{
    return transport_and_data_link_layer_set(usr_data, data_size, swap);
}

int32_t transport_resolve_fragment_interface(const uint8_t *buf, lite_frame_swap_t *swap)
{
    return transport_resolve_fragment(buf, swap);
}